import { PlusOutlined, UploadOutlined } from "@ant-design/icons";
import type { UploadProps } from "antd";
import { Button, Flex, message, Upload } from "antd";
import { filter, isEmpty, join, map } from "lodash";
import { useCallback, useEffect, useRef, useState } from "react";
import styles from "./index.module.less";
import { UploadListType } from "antd/es/upload/interface";
import { useSelector } from "@/store/hooks";
import update from "immutability-helper";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import DragableUploadListItem from "./DragableUploadListItem";
import { isDevFn } from "@/utils/getEnv";

interface Props {
	canDownload?: boolean;
	canRemove?: boolean;
	url?: string;
	isView?: boolean;
	maxCount?: number;
	msg?: string;
	uploadNode?: React.ReactNode;
	showUploadListConfig?: any;
	listType?: UploadListType;
	maxSize?: number;
	isShowUploadBtn?: boolean;
	resFormat?: (res: any) => any;
	canDrag?: boolean;
	accept?: string;
	iconRender?: any;
	data?: any;
}

export default (props: Props) => {
	const token = useSelector(state => state.global.token);
	const {
		canRemove = true,
		url,
		isView,
		canDownload = false,
		maxCount = 1,
		msg,
		uploadNode,
		showUploadListConfig,
		listType,
		maxSize = 5,
		isShowUploadBtn,
		resFormat,
		canDrag,
		accept: propsAccept,
		iconRender,
		data
	} = props;
	const [list, setList] = useState<any>([]);
	const accept = propsAccept ?? ".png,.jpg,.jpeg,.webp,image/png,image/jpg,image/jpeg";

	//数据回填，是否是第一次请求
	const flag = useRef(true);

	const handleChange = (currentList: any) => {
		props?.onChange(resFormat ? resFormat(currentList) : currentList);
	};

	const isDev = isDevFn(import.meta.env.MODE);

	const _props: UploadProps = {
		name: "file",
		action: url ?? `${isDev ? "" : import.meta.env.VITE_API_URL}/api/upload/qiniu`,
		headers: {
			token
		},
		data: data ?? {},
		accept: accept,
		multiple: true,
		maxCount: maxCount,
		fileList: list,
		listType: listType ?? "picture-card",
		beforeUpload: file => {
			let arr = accept?.split(",") || [];

			const fileType = file?.name?.split(".")?.at(-1);

			return new Promise((resolve, reject) => {
				if (arr.includes(`.${fileType}`)) {
					if (file.size / 1024 / 1024 < maxSize) {
						return resolve(file);
					} else {
						message.error(`上传附件大小限制${maxSize}MB以内。`);
					}
				} else {
					message.error("请选择正确的文件格式上传");
				}
			});
		},
		showUploadList: showUploadListConfig ?? {
			showRemoveIcon: canRemove,
			showDownloadIcon: canDownload,
			showPreviewIcon: false
		},
		onRemove: (file: any) => {
			const newList = list?.filter(i => i.uid !== file.uid && file?.url);

			setList(newList);
			handleChange(newList);
			Promise.resolve(true);
		},
		onDownload: async () => {},
		onChange({ file, fileList }) {
			if (file.status === "uploading") {
			}
			setList(fileList);
			if (file.status === "done") {
				if (file.response?.code === 1 && file.response?.data) {
					message.success(`${file.name} 上传成功！`);
					handleChange(
						map(fileList, i => ({
							...i,
							url: i.response?.data || i.url
						}))
					);
				}
			} else if (file.status === "error") {
				const newList = fileList?.filter(i => i.uid !== file.uid);
				handleChange(newList);
				setList(newList);
				message.error(`${file.name} 上传失败！`);
			} else if (file.status === "removed") {
			}
		},
		progress: {
			format: percent => percent && `${parseFloat(percent.toFixed(2))}%`
		},
		iconRender: iconRender
	};

	useEffect(() => {
		if (props.value && isEmpty(list) && flag.current) {
			flag.current = false;

			const getItem = (url: string, index: number) => ({
				url,
				uid: Date.now() + index,
				name,
				status: "done"
			});
			const list = Array.isArray(props.value) ? props.value?.map((i, index) => getItem(i, index)) : [getItem(props.value)];
			handleChange(list);
			setList(list);
		}
	}, [props.value]);

	const getNode = (attr: any = {}) => {
		return (
			<>
				{Boolean(msg) && <div className={styles.msg}>{msg}</div>}
				<Upload {..._props} {...attr} className={styles.container}>
					{((!isView && list.length < maxCount) || isShowUploadBtn) &&
						(uploadNode ?? (
							<Flex vertical={true} align="center" justify="center">
								<PlusOutlined style={{ fontSize: "18px", color: "#8F8F8F" }} />
								<span style={{ color: "#8F8F8F" }}>上传图片</span>
							</Flex>
						))}
				</Upload>
			</>
		);
	};

	const moveRow = useCallback(
		(dragIndex: number, hoverIndex: number) => {
			const dragRow = list[dragIndex];
			setList(
				update(list, {
					$splice: [
						[dragIndex, 1],
						[hoverIndex, 0, dragRow]
					]
				})
			);
		},
		[list]
	);

	return canDrag ? (
		<DndProvider backend={HTML5Backend}>
			{getNode({
				itemRender: (originNode, file, currFileList) => (
					<DragableUploadListItem originNode={originNode} file={file} fileList={currFileList} moveRow={moveRow} />
				)
			})}
		</DndProvider>
	) : (
		getNode()
	);
};
